<?php
/**
 * Copyright (c) [2019] [吴跃忠]
 * [selibra] is licensed under the Mulan PSL v1.
 * You can use this software according to the terms and conditions of the Mulan PSL v1.
 * You may obtain a copy of Mulan PSL v1 at:
 * http://license.coscl.org.cn/MulanPSL
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
 * PURPOSE.
 * See the Mulan PSL v1 for more details.
 */

namespace Selibra\Http\Annotations;

use Selibra\Di\AnnotationConfigure;
use Selibra\Di\AnnotationExecEntity;
use Selibra\Di\Annotations\Protocol\SelibraAnnotationInterface;
use Selibra\Http\Route\ControllerBaseRouteMapper;
use Selibra\Http\Route\RouterConfig;
use Selibra\Http\Route\RouterMapper;
use \Attribute;
use Selibra\Tools\Console;

/**
 * Class Route
 * @package selibra\http\annotation
 */
#[Attribute(Attribute::TARGET_METHOD)]
final class Route implements SelibraAnnotationInterface
{


    /**
     * @var string
     */
    protected string $alias;


    /**
     * @var string
     */
    protected string $type = 'ANY';

    protected float $version = -1;

    /**
     * Route constructor.
     * @param string $alias
     * @param string $method
     * @param float $version 接口版本，默认为0.1版本
     */
    public function __construct(string $alias, $method = "ANY", float $version = -1)
    {
        $this->alias = $alias;
        $this->type = $method;
        $this->version = $version;
    }


    /**
     * @inheritDoc
     */
    public function exec(AnnotationExecEntity &$annotationExecEntity)
    {
        if (isset($this->alias)) {
            $this->alias = $this->alias === '/' ? '' : $this->alias;

            // 分离动态参数
            $params = $this->perParams();

            // 获取控制器的基础路由
            $controllerRouteBase = ControllerBaseRouteMapper::get($annotationExecEntity->getClass());
            $alias = $controllerRouteBase . $this->alias;
            // 去除多余的 /
            $alias = str_replace('//', '/', $alias);

            // 写入到路由中
            $methodName = $annotationExecEntity->getMethod()->getName();
            $routerConfig = new RouterConfig();
            $routerConfig->setVersion($this->version);
            $routerConfig->setParams($params);
            $routerConfig->setAlias($alias);
            $routerConfig->setType($this->type);
            $routerConfig->setClass($annotationExecEntity->getClass());
            $routerConfig->setMethod($methodName);
            RouterMapper::createRoute($routerConfig);
        }
    }


    /**
     * 判断是顺序数组还是关联数组
     * @param array $inputArray
     * @return bool
     */
    function isArrayKeyNumericSequentialZeroBased(array $inputArray)
    {
        if (!is_array($inputArray)) {
            return false;
        }
        if (count($inputArray) <= 0) {
            return true;
        }
        return array_keys($inputArray) === range(0, count($inputArray) - 1);
    }

    /**
     * @inheritDoc
     */
    public function configure(AnnotationConfigure $annotationConfigure)
    {
        return $annotationConfigure->setRelyOnComponent(Controller::class);
    }

    /**
     * 预定义参数
     * @return array
     */
    private function perParams()
    {
        $params = [];
        $aliasArray = explode('/', $this->alias);
        foreach ($aliasArray as $key => $item) {
            if (!empty($item)) {
                if (str_starts_with($item, '{') && str_ends_with($item, '}')) {
                    // 动态参数
                    $params[] = substr($item, 1, -1);
                    continue;
                } elseif (empty($params)) {
                    $this->alias = implode('/', array_slice($aliasArray, 0, $key + 1));
                }
            }
        }
        return $params;
    }

}
